<template>
  <a-modal
    id="image-cropper"
    v-model:visible="visible"
    title="编辑图片"
    :footer="false"
    @cancel="closeModal"
  >
    <!--比例选择-->
    <div class="aspect-ratio-select">
      <a-radio-group v-model:value="aspectRatio">
        <a-radio value="free">自由比例</a-radio>
        <a-radio value="1:1">1:1</a-radio>
        <a-radio value="4:3">4:3</a-radio>
        <a-radio value="16:9">16:9</a-radio>
        <a-radio value="3:4">3:4</a-radio>
        <a-radio value="9:16">9:16</a-radio>
      </a-radio-group>
    </div>
    <!--  编辑组件  -->
    <vue-cropper
      ref="cropperRef"
      :img="imageUrl"
      :autoCrop="true"
      :fixedBox="false"
      :centerBox="true"
      :canMoveBox="true"
      :infoTrue="true"
      :info="true"
      :full="true"
      outputType="png"
      :fixed="aspectRatio != 'free'"
      :fixedNumber="currentAspectRatio"
    />
    <div style="margin-bottom: 16px"></div>
    <!-- 操作部分 -->
    <div class="image-cropper-actions">
      <a-space>
        <a-button @click="rotateLeft" :disabled="!canEdit">向左旋转</a-button>
        <a-button @click="rotateRight" :disabled="!canEdit" >向右旋转</a-button>
        <a-button @click="changeScale(1)" :disabled="!canEdit">放大</a-button>
        <a-button @click="changeScale(-1)" :disabled="!canEdit">缩小</a-button>
        <a-button type="primary" :loading="loading" :disabled="!canEdit" @click="handleConfirm">确认</a-button>
      </a-space>
    </div>
    <div style="margin-bottom: 16px"></div>
    <!-- 协同编辑操做 -->
    <div class="image-edit-action" v-if="isTeamSpace">
      <a-space>
        <a-button v-if="editingUser" disabled>{{ editingUser.userName }}正在编辑</a-button>
        <a-button v-if="canEnterEdit" type="primary" ghost @click="enterEdit">进入编辑</a-button>
        <a-button v-if="canExitEdit" danger ghost @click="exitEdit">退出编辑</a-button>
      </a-space>
    </div>
  </a-modal>
</template>

<script setup lang="ts">
import { computed, onUnmounted, ref, watch, watchEffect } from 'vue'
import { uploadPictureUsingPost } from '@/request/api/pictureController.ts'
import { message } from 'ant-design-vue'
import { useLoginUserStore } from '@/stores/useUserLoginStore.ts'
import  PictureEditWebSocket from '@/utils/webSocketUtil.ts'
import {
  PICTURE_EDIT_ACTION_ENUM,
  PICTURE_EDIT_MESSAGE_TYPE_ENUM,
} from '@/constants/pictureConstant.ts'
import { SPACE_TYPE_ENUM } from '@/constants/spaceUserConstant.ts'

interface Props {
  imageUrl?: string
  picture?: API.PictureVO
  spaceId?: number
  space?: API.SpaceVO
  onSuccess?: (newPicture: API.PictureVO) => void
}

const props = defineProps<Props>()
const loading = ref<boolean>(false)
const visible = ref<boolean>(false)
const cropperRef = ref()
const aspectRatio = ref<string>('free')
// 计算当前选择的比例
const currentAspectRatio = computed(() => {
  if (aspectRatio.value === 'free') return [0, 0]
  const [width, height] = aspectRatio.value.split(':').map(Number)
  return [width, height]
})

// 缩放：1放大,-1缩小
const changeScale = (num: number) => {
  cropperRef.value.changeScale(num)
  // 通知其他编辑者,放大或者缩小
  if (num > 0) {
    editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_IN)
  } else {
    editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT)
  }
}
// 左旋
const rotateLeft = () => {
  cropperRef.value.rotateLeft()
  // 通知其他编辑者，左旋
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT)
}
// 右旋
const rotateRight = () => {
  cropperRef.value.rotateRight()
  // 通知其他编辑者，右旋
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT)
}
// 确认裁剪
const handleConfirm = () => {
  // 拿到裁剪后的图片
  cropperRef.value.getCropBlob((blob: Blob) => {
    const fileName = (props.picture?.name || 'image') + '.png'
    const file = new File([blob], fileName, { type: blob.type })
    // 上传图片
    handleUpload({ file })
  })
}
// 上传图片
const handleUpload = async ({ file }: any) => {
  loading.value = true
  try {
    // 有图片就是修改，没有图片就是添加
    const params: API.uploadPictureUsingPOSTParams = props.picture ? { id: props.picture.id } : {}
    params.spaceId = props.spaceId
    let { data: res } = await uploadPictureUsingPost(params, {}, file)
    if (res.code === 0 && res.data) {
      // 上传成功
      message.success('上传成功')
      // 将信息返回给父组件
      props.onSuccess?.(res.data)
      closeModal()
    } else {
      // 上传失败
      message.error('上传失败' + res.message)
    }
  } catch (e) {
    // 上传失败
    message.error('上传失败' + e)
  } finally {
    loading.value = false
  }
}

// -------实时编辑图片---------
const loginUserStore = useLoginUserStore()
const loginUser = loginUserStore.loginUser
// 正在编辑的用户
let editingUser = ref<API.UserVO>()

// 没有正在编辑的用户可以进入编辑
const canEnterEdit = computed(() => {
  return !editingUser.value
})
// 正在编辑的是本人，可以退出编辑
const canExitEdit = computed(() => {
  return editingUser.value?.id === loginUser.id
})
// 是否为团队空间
const isTeamSpace = computed(() => {
  return props.space?.spaceType===SPACE_TYPE_ENUM.TEAM
})

// 正在编辑的是本人,可以编辑
const canEdit = computed(() => {
  // 不是团队空间默认能够编辑
  if (!isTeamSpace.value) {
    return true;
  }
  return editingUser.value?.id === loginUser.id
})
let websocket: PictureEditWebSocket | null

// 初始化websocket连接，绑定事件
const initWebSocket = () => {
  const pictureId = props.picture?.id
  if (!pictureId || !visible.value) {
    return
  }
  // 当有图片时并且弹框打开时,才初始化
  // 防止之前的连接未关闭
  if (websocket) {
    websocket.disconnect()
  }
  // 创建websocket实例
  const url = `ws://localhost:8123/api/ws/picture/edit?pictureId=${pictureId}`
  websocket = new PictureEditWebSocket(url)
  // 建立连接
  websocket.connect()
  // 监听消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.INFO, (msg) => {
    console.log('收到通知消息', msg)
    message.info(msg.message)
  })
  // 监听错误消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ERROR, (msg) => {
    console.log('收到错误消息', msg)
    message.error(msg.message)
  })
  // 监听进入编辑状态的消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT, (msg) => {
    console.log('收到进入编辑状态的消息', msg)
    message.info(msg.message)
    // 记录当前编辑的用户
    editingUser.value = msg.user
  })
  // 监听编辑操作的消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION, (msg) => {
    console.log('收到编辑操作的消息', msg)
    message.info(msg.message)
    switch (msg?.editAction) {
      // 放大
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_IN:
        changeScale(1)
        break
      // 缩小
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT:
        changeScale(-1)
        break
      // 左旋
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT:
        rotateLeft()
        break
      // 右旋
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT:
        rotateRight()
        break
    }
  })
  // 监听退出编辑的状态
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT, (msg: any) => {
    console.log('收到退出编辑的消息', msg)
    message.info(msg.message)
    editingUser.value = undefined
  })
}
watchEffect(() => {
  // 团队空间才会触发初始化
  if (isTeamSpace.value) {
    // 当这个方法里的任意属性发送改变时触发
    initWebSocket()
  }
})
onUnmounted(() => {
  // 断开连接
  if (websocket) {
    websocket.disconnect()
    websocket = null
  }
  editingUser.value = undefined
})

// 关闭模态框
const closeModal = () => {
  visible.value = false
  // 断开连接
  if (websocket) {
    websocket.disconnect()
  }
  editingUser.value = undefined
}
// 打开模态框
const openModal = () => {
  visible.value = true
}
// 进入编辑时
const enterEdit = () => {
  if (websocket) {
    // 发送进入编辑状态的消息
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT,
    })
  }
}
// 退出编辑时
const exitEdit = () => {
  if (websocket) {
    // 发送退出编辑状态的消息
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT,
    })
  }
}
// 编辑图片操作
const editAction = (editAction: string) => {
  if (websocket) {
    // 发送编辑操作请求
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION,
      editAction,
    })
  }
}


// 暴露给父组件
defineExpose({
  openModal,
})
</script>

<style lang="less" scoped>
#image-cropper {
  align-content: center;
}

.vue-cropper {
  height: 400px;
}
</style>
